//
// Created by casdon on 2024/8/19.
//

#ifndef CIOT_CSDK_CIOT_CLINK_H
#define CIOT_CSDK_CIOT_CLINK_H

#include "types.h"

#if CLINK_USE_WLAN
#include "wlan.h"
#endif
#include <ciot/wlan.h>

#ifdef __cplusplus
extern "C" {
#endif

#define CLINK_MAX_WIFI_RETRY    3
#define CLINK_WIFI_CONNECTION_DURATION  10
#define CLINK_CLOUD_CONNECTION_MAX_DURATION     30*1000

#define CLINK_DEFAULT_ADVERTISING_TIMEOUT 3 * 60 * 1000

typedef enum Ciot_clink_connection_status_e{

    Clink_status_idle = 0,              // 未开启

    Clink_status_device_advertising,    // 设备广播中                "device_advertising"
    Clink_status_device_handshaking,    // 与设备握手中   * 物理层握手   "device_handshaking"
    Clink_status_device_connected,      // 设备连接成功   * 物理层连接   "device_connected"
    Clink_status_device_verified,       // 设备认证成功           "device_verified"
    Clink_status_device_invalid,        // 设备不合法             "device_invalid"
    Clink_status_device_sign_failed,    // APP不合法             "device_sign_failed"
    Clink_status_communication_timeout, // 通讯超时               "communication_timeout"
    Clink_status_device_connect_max_count,// 设备连接次数超过最大次数 "device_connect_max_count"

    Clink_status_ap_will_disconnect,    // AP连接即将断开         "ap_will_disconnect"
    // AP联网时收到该事件需要主动去云端拿到后续配网状态

    Clink_status_wifi_connecting,       // 设备联网中            "wifi_connecting"
    Clink_status_wifi_connected,        // 设备联网成功           "wifi_connected"
    Clink_status_wifi_timeout,          // Wi-Fi连接超时         "wifi_timeout"
    Clink_status_wifi_pass_err,         // Wi-Fi账号密码错误      "wifi_pass_err"

    Clink_status_cloud_connecting,      // 设备入云中               "cloud_connecting"
    Clink_status_cloud_connected,       // 设备入云成功             "cloud_connected"

    Clink_status_cloud_bind,         // 设备绑定认证                "cloud_bind"

    Clink_status_cloud_unbind,          // 设备被云端解绑            "cloud_unbind"
    Clink_status_app_unbind,          // 设备被APP解绑            "app_unbind"

    Clink_status_cloud_auth_failed,     // 入云失败，设备不合法       "cloud_auth_failed"
    Clink_status_cloud_timeout,         // 入云失败，连接超时        "cloud_timeout"
    Clink_status_cloud_rebind,          // 入云失败，重复绑定        "cloud_rebind"
    Clink_status_cloud_denied,          // 入云失败，设备被禁用       "cloud_denied"
    Clink_status_cloud_user_invalid,    // 入云失败，非法用户        "cloud_user_invalid"

    Clink_status_wifi_disconnected,     // 配网失败，网络断开        "wifi_disconnected"
    Clink_status_cloud_disconnected,    // 配网失败，云端断开        "cloud_disconnected"

    Clink_status_succeed,               // 配网成功                 "succeed"
    Clink_status_timeout,               // 超时                    "timeout"
    Clink_status_no_wifi_setting,       // 没有Wi-Fi设置            "no_wifi_setting"

    Clink_status_MAX
} Ciot_clink_connection_status;

typedef enum Ciot_qr_size_e{
    CIOT_QR_SIZE_32 = 1,
    CIOT_QR_SIZE_64 = 2,
    CIOT_QR_SIZE_128 = 4,
    CIOT_QR_SIZE_256 = 8,
    CIOT_QR_SIZE_512 = 16,
    CIOT_QR_SIZE_1024 = 32
}Ciot_qr_size;

const char * clink_check_status_msg( Ciot_clink_connection_status status );
Ciot_clink_connection_status clink_check_status_str( const char* status_str );

typedef struct ciot_clink_manager_t
{
    bool     (*isBroadcasting) (void);
    Ciot_res (*broadcast) (void);

    Ciot_res (* check_status) (void);

    const char* (* get_ssid)( void );
    const char* (* get_pass)( void );

    Ciot_res (* set_ssid) ( const char * ssid, uint8_t len );
    Ciot_res (* set_pass) ( const char * pass, uint8_t len );

    Ciot_res (* start) (Ciot_time_ms timeout_ms);

    Ciot_res (* set_advertising_timeout) (Ciot_time_ms timeout_ms);
    Ciot_res (* set_handshaking_timeout) (Ciot_time_ms timeout_ms);
    Ciot_res (* set_wifi_connection_timeout) (Ciot_time_ms timeout_ms);
    Ciot_res (* set_cloud_connection_timeout) (Ciot_time_ms timeout_ms);
    Ciot_res (* clear_timeout ) (void);
    Ciot_res (* exit_with_error ) ( Ciot_clink_connection_status error_status );
    Ciot_res (* reset_with_error ) ( Ciot_clink_connection_status error_status );

    Ciot_res (* stop)  (void);

    Ciot_res (* ble_verify) (void);
    Ciot_res (* ap_verify) (void);

    Ciot_res (* sta_done) (void);
    Ciot_res (* sta_disconnected) (void);

    CIOT_PRIVATE
    Ciot_res (* cloud_status_update)( Ciot_clink_connection_status cloud_status );
    Ciot_sta_status (* get_sta_status) (void);

    CIOT_NOTIFY
    Ciot_res (* clink_event_notify)(Ciot_clink_connection_status status, void * data);

    Ciot_clink_connection_status (* current_status) (void);

    Ciot_res (* start_connect_notify) (void);
    Ciot_res (* cannot_start_connect_notify) (void);
    uint8_t* (*get_qr_url)(void);//get long qr code url
    Ciot_res (*generate_qr_image_data)(const char *url, Ciot_qr_size scale);//scale:2,4,8,16 -> 64x64、128x128、256x256、512x512

} ciot_clink_manager;

#if CLINK_USE_WLAN
typedef Ciot_res (*clink_wifi_event_notify)(Ciot_clink_connection_status cloud_status, ciot_wlan_ap_config * config);
#endif
typedef Ciot_res (*clink_common_event_notify)(Ciot_clink_connection_status cloud_status, void * config);

CIOT_PRIVATE
const ciot_clink_manager * ciot_clink_manager_init();

CIOT_API
const ciot_clink_manager * ciot_clink_manager_instance();

CIOT_API
Ciot_res ciot_clink_watch_event( clink_common_event_notify callback );

#define ciot_clink_mgr()    ciot_clink_manager_instance()
#define ciot_clink()        ciot_clink_mgr()



#ifdef __cplusplus
}
#endif

#endif //CIOT_CSDK_CIOT_CLINK_H
